package com.bd.demo;

import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
import com.bd.demo.app.MyApp;
import com.clj.fastble.BleManager;
import com.clj.fastble.data.BleDevice;
import com.hailiao.bdproto2p1.BDProto2p1;
import com.hailiao.bdproto2p1.bean.basic.BDBSI_Bean;
import com.hailiao.bdproto2p1.bean.basic.BDICI_Bean;
import com.hailiao.bdproto2p1.bean.basic.BDTXR_Bean;
import com.hailiao.bdproto2p1.bean.basic.CCICA_Bean;
import com.hailiao.bdproto2p1.bean.basic.CCRMO_Bean;
import com.hailiao.bdproto2p1.bean.basic.CCTXA_Bean;
import com.hailiao.bdproto2p1.proto.Proto2p1Basic;
import com.hailiao.bdproto2p1.worker.BasicWorker2p1;
import com.hailiao.hlbdcore.HLBDCore;
import com.hailiao.hlbdcore.annotation.HLBDReceive;
import com.hailiao.hlbdcore.annotation.HLBDSend;
import com.hailiao.hlbdcore.base.BaseBDProto;
import com.hailiao.hlbdcore.base.BaseInBean;
import com.hailiao.hlbdcore.base.BaseOutBean;
import com.hailiao.hlbdcore.base.HLBDClient;
import com.hailiao.hlbluetoothlib.HLBleManager;
import com.hailiao.hlbluetoothlib.constant.BleStatus;
import java.util.List;
import kotlin.coroutines.Continuation;
import kotlin.coroutines.CoroutineContext;
import kotlinx.coroutines.Dispatchers;

public class Test {

    /**
     * 蓝牙相关
     */
    private static void ble() {
        // 手机蓝牙开关状态
        BleManager.getInstance().isBlueEnable();
        // 打开蓝牙
        BleManager.getInstance().enableBluetooth();
        // 蓝牙模块初始化
        HLBleManager ble = HLBleManager.instance(MyApp.Companion.instance());
        // 获取蓝牙状态（可监听）
        MutableLiveData<BleStatus> statusLive = ble.getBleStatusLive();
        statusLive.observeForever(bleStatus -> {
            // 蓝牙状态更新
            switch (bleStatus) {
                case CONNECTED:
                    // 已连接
                    break;
                case CONNECTING:
                    // 正在连接
                    break;
                case DISCONNECT:
                    // 已断开连接
                    break;
                case DISABLE:
                    // 已关闭
                    break;
            }
        });
        // 获取蓝牙状态（当前）
        statusLive.getValue();
        // 设置打印开关
        ble.setLogEnable(true);
        // 判断蓝牙是否连接
        ble.isBleConnected();
        // 扫描蓝牙设备
        ble.scanDevice(new Continuation<List<? extends BleDevice>>() {
            @NonNull
            @Override
            public CoroutineContext getContext() {
                // 在IO线程进行
                return Dispatchers.getIO();
            }

            @Override
            public void resumeWith(@NonNull Object o) {
                // 得到结果
                List<BleDevice> list = (List<BleDevice>) o;
            }
        });
        // 获取已经扫描到的设备列表
        MutableLiveData<List<BleDevice>> scanList = ble.getScanDeviceListLive();
        // 获取已经连接的蓝牙设备列表
        MutableLiveData<List<BleDevice>> connectList = ble.getConnectedDeviceListLive();
        // 连接蓝牙设备
        // * 通过BleDevice连接
        ble.connectDevice(scanList.getValue().get(0), new Continuation<Boolean>() {
            @NonNull
            @Override
            public CoroutineContext getContext() {
                // 在IO线程进行
                return Dispatchers.getIO();
            }

            @Override
            public void resumeWith(@NonNull Object o) {
                // 得到结果
                boolean isSuccess = (boolean)o;
            }
        });
        // * 通过蓝牙Mac地址连接
        ble.connectDevice("11:22:33:44", new Continuation<Boolean>() {
            @NonNull
            @Override
            public CoroutineContext getContext() {
                // 在IO线程进行
                return Dispatchers.getIO();
            }

            @Override
            public void resumeWith(@NonNull Object o) {
                // 得到结果
                boolean isSuccess = (boolean)o;
            }
        });
        // 打开设备通知特征
        ble.startNotify(scanList.getValue().get(0), new Continuation<Boolean>() {
            @NonNull
            @Override
            public CoroutineContext getContext() {
                // 在IO线程进行
                return Dispatchers.getIO();
            }

            @Override
            public void resumeWith(@NonNull Object o) {
                // 得到结果
                boolean isSuccess = (boolean)o;
            }
        });
    }

    /**
     * 连接设备完整流程
     * @param device
     */
    public static void connectBleDevice(BleDevice device) {
        HLBleManager ble = HLBleManager.instance(MyApp.Companion.instance());
        ble.connectDevice(device, getNewBoolContinuation(isSuccess -> {
            if (isSuccess) {
                // 连接成功，打开通知
                ble.startNotify(device, getNewBoolContinuation(isNotifySuccess -> {
                    if (isNotifySuccess) {
                        // 完全连接成功
                        // todo
                    } else  {
                        // 打开通知失败
                    }
                }));
            } else {
                // 连接失败
            }
        }));
    }

    private static Continuation<Boolean> getNewBoolContinuation(ContinuationResume<Boolean> listener) {
        return new Continuation<Boolean>() {
            @NonNull
            @Override
            public CoroutineContext getContext() {
                // 在IO线程进行
                return Dispatchers.getIO();
            }

            @Override
            public void resumeWith(@NonNull Object o) {
                listener.resume((boolean)o);
            }
        };
    }

    public interface ContinuationResume<T> {
        void resume(T o);
    }

    /**
     * 判断手机位置信息是否打开
     * @param c
     * @return [Boolean] true:已打开; false:未打开;
     */
    public boolean isLocationServerEnabled(Context c) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            int locationMode = 0;
            try {
                locationMode = Settings.Secure.getInt(c.getContentResolver(), Settings.Secure.LOCATION_MODE);
            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            return locationMode != Settings.Secure.LOCATION_MODE_OFF;
        } else {
            String locationProviders = Settings.Secure.getString(c.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            return !locationProviders.isEmpty();
        }
    }

    /**
     * 协议
     */
    public void proto2p1() {
        // 协议初始化
        BDProto2p1.INSTANCE.init();
        HLBleManager ble = HLBleManager.instance(MyApp.Companion.instance());
        String mac = "11:22:33:44";

        // CCICA- BDICI 读取北斗设备的加密模块信息
        BasicWorker2p1.INSTANCE.ccica(ble, mac, new CCICA_Bean(), new Continuation<BDICI_Bean>() {
            @NonNull
            @Override
            public CoroutineContext getContext() {
                // 在IO线程进行
                return Dispatchers.getIO();
            }

            @Override
            public void resumeWith(@NonNull Object o) {
                // 得到结果
                BDICI_Bean bean = (BDICI_Bean) o;
            }
        });
        // CCRMO 指令输出控制
        BasicWorker2p1.INSTANCE.ccrmo(ble, mac, new CCRMO_Bean(), new Continuation<BaseOutBean>() {
            @NonNull
            @Override
            public CoroutineContext getContext() {
                // 在IO线程进行
                return Dispatchers.getIO();
            }

            @Override
            public void resumeWith(@NonNull Object o) {
                // 得到结果
                BaseOutBean bean = (BaseOutBean) o;
                // 判断是否发送成功
                bean.isSuccess();
                // 获取发送失败错误码
                bean.getErrorType();
            }
        });

        // 监听 【接收、发送】 协议指令
        // * 注册协议监听器
        HLBDCore.INSTANCE.register(this);
    }

    public void init() {
        BDProto2p1.INSTANCE.init();
        HLBDCore.INSTANCE.register(this);
    }

    @HLBDSend
    public void onHLSend(
            HLBDClient client,
            String device,
            byte[] raw,
            boolean isCanAnalysis,
            BaseBDProto proto,
            BaseInBean bean
    ) {
        if (Proto2p1Basic.TXA == proto) {
            // 发送TXA
            CCTXA_Bean cctxa = (CCTXA_Bean) bean;
        }
    }

    @HLBDReceive
    public void onHLReceive(
            HLBDClient client,
            String device,
            byte[] raw,
            boolean isCanAnalysis,
            BaseBDProto proto,
            BaseOutBean bean
    ) {
        System.out.println("onHLReceive");
        if (Proto2p1Basic.TXR == proto) {
            // 接收北斗短报文消息
            BDTXR_Bean bdtxr = (BDTXR_Bean) bean;
            System.out.println(bdtxr.toReadString());
        } else if (Proto2p1Basic.BSI == proto) {
            // 信号状态
            BDBSI_Bean bdbsi = (BDBSI_Bean) bean;
        }
    }
}
